﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace DES
{
    public partial class DES : Form
    {
        public DES()
        {
            InitializeComponent();
        }

        public List<int> aList = new List<int>();
        public List<int> opList = new List<int>();

        static long[] k = new long[17];//保存生成的16个子密钥，下标从1~16

        //static void Execute()
        //{
        //    long key = Convert.ToInt64("3531313033313139", 16);
        //    long input = Convert.ToInt64("3531313033313139", 16);
        //    long output;

        //    output = encrypt(input, key);

        //    Console.WriteLine(Convert.ToString(output, 16));

        //    output = decipher(output, key);
        //    Console.WriteLine(Convert.ToString(output, 16));

        //    Console.Read();

        //}

        //改进的S置换数组
        byte[,] SuperS = new byte[8, 64] {
                           {14,0,4,15,13,7,1,4,2,14,15,2,11,13,8,1,3,10,10,6,6,12,12,11,5,9,9,5,0,3,7,8,4,15,
                            1,12,14,8,8,2,13,4,6,9,2,1,11,7,15,5,12,11,9,3,7,14,3,10,10,0,5,6,0,13},

                           {15,3,1,13,8,4,14,7,6,15,11,2,3,8,4,14,9,12,7,0,2,1,13,10,12,6,0,9,5,11,10,5,0,13,
                            14,8,7,10,11,1,10,3,4,15,13,4,1,2,5,11,8,6,12,7,6,12,9,0,3,5,2,14,15,9},

                           {10,13,0,7,9,0,14,9,6,3,3,4,15,6,5,10,1,2,13,8,12,5,7,14,11,12,4,11,2,15,8,1,13,1,
                            6,10,4,13,9,0,8,6,15,9,3,8,0,7,11,4,1,15,2,14,12,3,5,11,10,5,14,2,7,12},

                           {7,13,13,8,14,11,3,5,0,6,6,15,9,0,10,3,1,4,2,7,8,2,5,12,11,1,12,10,4,14,15,9,10,3,
                            6,15,9,0,0,6,12,10,11,1,7,13,13,8,15,9,1,4,3,5,14,11,5,12,2,7,8,2,4,14},

                           {2,14,12,11,4,2,1,12,7,4,10,7,11,13,6,1,8,5,4,0,3,15,15,10,13,3,0,9,14,8,9,6,4,11,
                            2,8,1,12,11,7,10,1,13,14,7,2,8,13,15,6,9,15,12,0,5,9,6,10,3,4,0,5,14,3},

                           {12,10,1,15,10,4,15,2,9,7,2,12,6,9,8,5,0,6,13,1,3,13,4,14,14,0,7,11,5,3,11,8,9,4,
                            14,3,15,2,5,12,2,9,8,5,12,15,3,10,7,11,0,14,4,1,10,7,1,6,13,0,11,8,6,13},

                           {4,13,11,0,2,11,14,7,15,4,0,9,8,1,13,10,3,14,12,3,9,5,7,12,5,2,10,15,6,8,1,6,1,6,
                            4,11,11,13,13,8,12,1,3,4,7,10,14,7,10,9,15,5,6,0,8,15,0,14,5,2,9,3,2,12},

                           {13,1,2,15,8,13,4,8,6,10,15,3,11,7,1,4,10,12,9,5,3,6,14,11,5,0,0,14,12,9,7,2,7,2,
                            11,1,4,14,1,7,9,4,12,10,14,8,2,13,0,15,6,12,10,9,13,0,15,3,3,5,5,6,8,11}};

        int[] ipM = {58,50,42,34,26,18,10,2,
                      60,52,44,36,28,20,12,4,
                      62,54,46,38,30,22,14,6,
                      64,56,48,40,32,24,16,8,
                      57,49,41,33,25,17,9,1,
                      59,51,43,35,27,19,11,3,
                      61,53,45,37,29,21,13,5,
                      63,55,47,39,31,23,15,7};

        int[] ipRevM = { 40,  8, 48, 16, 56, 24, 64, 32,
                        39,  7, 47, 15, 55, 23, 63, 31,
                        38,  6, 46, 14, 54, 22, 62, 30,
                        37,  5, 45, 13, 53, 21, 61, 29,
                        36,  4, 44, 12, 52, 20, 60, 28,
                        35,  3, 43, 11, 51, 19, 59, 27,
                        34,  2, 42, 10, 50, 18, 58, 26,
                        33,  1, 41,  9, 49, 17, 57, 25};

        int[] eM = { 32,  1,  2,  3,  4,  5,
                         4,  5,  6,  7,  8,  9, 
                         8,  9, 10, 11, 12, 13, 
                        12, 13, 14, 15, 16, 17,
                        16, 17, 18, 19, 20, 21,
                        20, 21, 22, 23, 24, 25, 
                        24, 25, 26, 27, 28, 29, 
                        28, 29, 30, 31, 32, 1 };

        int[] pM = { 16,  7, 20, 21, 
                        29, 12, 28, 17,
                         1, 15, 23, 26, 
                         5, 18, 31, 10,
                         2,  8, 24, 14, 
                        32, 27,  3,  9, 
                        19, 13, 30,  6,
                        22, 11,  4, 25 };

        int[] pc2M = { 14,17,11,24,1,5,
                     3,28,15,6,21,10,
                     23,19,12,4,26,8,
                     16,7,27,20,13,2,
                     41,52,31,37,47,55,
                     30,40,51,45,33,48,
                     44,49,39,56,34,53,
                     46,42,50,36,29,32};

        int[] pc1M = {57,49,41,33,25,17,9,
                     1,58,50,42,34,26,18,
                     10,2,59,51,43,35,27,
                     19,11,3,60,52,44,36,
                     63,55,47,39,31,23,15,
                     7,62,54,46,38,30,22,
                     14,6,61,53,45,37,29,
                     21,13,5,28,20,12,4};

        //加密算法
        long encrypt(long input, long key)
        {
            long output = 0;
            int[] l = new int[17];
            int[] r = new int[17];
            int i;

            input = ip(input);   //IP变换
            createKey(key);      //生成子密钥

            //左右对半分
            l[0] = (int)((input >> 32) & 0x0FFFFFFFF);
            r[0] = (int)(input & 0x0FFFFFFFF);

            for (i = 1; i < 16; i++)
            {
                l[i] = r[i - 1];
                r[i] = l[i - 1] ^ f(r[i - 1], k[i]);
            }


            r[16] = l[15] ^ f(r[15], k[16]);
            l[16] = r[15];

            output = ((long)l[16] & 0x0FFFFFFFF) | ((long)r[16] << 32);
            output = ip_1(output);
            return output;
        }

        //解密算法
        long decipher(long input, long key)
        {
            long output = 0;
            int[] l = new int[17];
            int[] r = new int[17];
            int i;

            input = ip(input);   //IP变换
            createKey(key);      //生成子密钥

            //左右对半分
            l[0] = (int)((input >> 32) & 0x0FFFFFFFF);
            r[0] = (int)(input & 0x0FFFFFFFF);

            for (i = 1; i < 16; i++)
            {
                l[i] = r[i - 1];
                r[i] = l[i - 1] ^ f(r[i - 1], k[17 - i]);
            }


            r[16] = l[15] ^ f(r[15], k[1]);
            l[16] = r[15];

            output = ((long)l[16] & 0x0FFFFFFFF) | ((long)r[16] << 32);
            output = ip_1(output);
            return output;
        }

        //IP变换
        long ip(long input)
        {
            long input2 = input;
            long output = 0;
            int count = 0;
            long key = 1;

            for (int i = 0; i < 64; i++)
            {
                if ((input2 & (key << (64 - ipM[i]))) != 0)
                {
                    output = output | (key << (63 - count));
                }
                count++;
            }
            return output;

        }

        //IP逆变换
        long ip_1(long input)
        {
            long input2 = input;
            long output = 0;
            int count = 0;
            long key = 1;

            for (int i = 0; i < 64; i++)
            {
                if ((input2 & (key << (64 - ipRevM[i]))) != 0)
                {
                    output = output | (key << (63 - count));
                }
                count++;
            }
            return output;

        }

        //f函数
        int f(int r, long k)
        {
            long temp;
            int output = 0;
            byte[] s_byte = new byte[9];
            int i;

            temp = e(r);
            temp = temp ^ k;

            for (i = 1; i <= 8; i++)
            {
                s_byte[i] = (byte)((temp >> 6 * (8 - i)) & 0x3F);
                s_byte[i] = s(s_byte[i], i);
                output |= (int)s_byte[i] << 4 * (8 - i);
            }

            output = p(output);
            return output;
        }

        /****改进S盒置换函数
      * 输入6位二进制和置换数组号1~8
      * 输出4位二进制******************/
        byte s(byte sixbyte, int n)
        {
            byte fourbyte = 0;



            fourbyte = SuperS[n - 1, sixbyte];
            return fourbyte;
        }

        //E变换
        long e(int r)
        {
            long input;
            long output;
            input = Convert.ToInt64(r) << 32;
            output = 0;
            int count = 16;
            long key = 1;

            for (int i = 0; i < 48; i++)
            {
                if ((input & (key << (64 - eM[i]))) != 0)
                {
                    output = output | (key << (63 - count));
                }
                count++;
            }
            return output;
        }

        //P变换
        int p(int input)
        {
            long temp;
            long output;
            temp = Convert.ToInt64(input) << 32;
            output = 0;
            int count = 32;
            long key = 1;

            for (int i = 0; i < 32; i++)
            {
                if ((temp & (key << (64 - pM[i]))) != 0)
                {
                    output = output | (key << (63 - count));
                }
                count++;
            }

            return (int)output;
        }

        //生成子密钥的函数
        void createKey(long key)
        {
            long key_pc1 = 0;
            int[] c = new int[17];
            int[] d = new int[17];
            long[] cd = new long[17];

            int i;

            //pc1变换
            key_pc1 = pc1(key);

            //左右平分
            c[0] = (int)((key_pc1 >> 28) & 0x0FFFFFFF);
            d[0] = (int)(key_pc1 & 0x0FFFFFFF);

            //循环左移，左右平分，生成16个子密钥
            for (i = 1; i <= 16; i++)
            {
                c[i] = ((c[i - 1] << 1) | (c[i - 1] >> 27)) & 0x0FFFFFFF;
                d[i] = ((d[i - 1] << 1) | (d[i - 1] >> 27)) & 0x0FFFFFFF;
                if (i != 1 && i != 2 && i != 9 && i != 16)
                {
                    c[i] = ((c[i] << 1) | (c[i] >> 27)) & 0x0FFFFFFF;
                    d[i] = ((d[i] << 1) | (d[i] >> 27)) & 0x0FFFFFFF;
                }
                cd[i] = (((long)c[i]) << 28) | ((long)d[i]);
                k[i] = pc2(cd[i]);
            }
        }

        //PC-1变换
        long pc1(long k)
        {
            long input = k;
            long output = 0;
            int count = 8;
            long key = 1;

            for (int i = 0; i < 56; i++)
            {
                if ((input & (key << (64 - pc1M[i]))) != 0)
                {
                    output = output | (key << (63 - count));
                }
                count++;
            }
            return output;
        }

        //PC-2变换
        long pc2(long k)
        {
            long input = Convert.ToInt64(k) << 8;
            long output = 0;
            int count = 16;
            long key = 1;

            for (int i = 0; i < 48; i++)
            {
                if ((input & (key << (64 - pc2M[i]))) != 0)
                {
                    output = output | (key << (63 - count));
                }
                count++;
            }
            return output;
        }

        /******生成64位密钥**********/
        long Check(long key)
        {
            long result = 0;
            long[] keylong = new long[8];
            keylong = c(key);
            for (int i = 0; i < 8; i++)
            {
                result |= keylong[i] << (56 - 8 * i);
            }
            return result;
        }

        /*****拆分56位，添加奇校验位**************************/
        long[] c(long key)
        {
            byte[] resultbyte = new byte[8]; //56位拆成7x8段
            byte[] countbyte = new byte[7]; //每段7位分为7个byte
            long[] resultlong = new long[8];//保存最终结果
            int m = 0;
            for (int i = 0; i < 8; i++)
            {
                m = 49 - 7 * i;
                resultbyte[i] = (byte)((key >> m) & 0x7f);

                int j = 0;
                int count = 0;
                while (j < 7)
                {
                    countbyte[j] = (byte)((resultbyte[i] >> (6 - j)) & 0x1);
                    if (countbyte[j] == 1)
                    {
                        count++;
                    }
                    j++;
                }
                if (count % 2 != 0)
                {
                    resultlong[i] = resultbyte[i] << 1;
                }
                else
                    resultlong[i] = (resultbyte[i] << 1) | 0x1;
            }
            return resultlong;
        }

 

        private void jiami_Click(object sender, EventArgs e)
        {
            if (mingwen.Text.Length == 16 && miyue.Text.Length == 14)
            {
                long key = Check(Convert.ToInt64(miyue.Text.ToString(), 16));
                long input = Convert.ToInt64(mingwen.Text.ToString(), 16);
                long output;
                output = encrypt(input, key);
                jiamihou.Text = Convert.ToString(output, 16);
                miyuequan.Text = Convert.ToString(key, 16);
            }
            else
            {
                MessageBox.Show("输入错误，请重新输入！", "错误", MessageBoxButtons.OK);
            }

        }

        private void jiemi_Click(object sender, EventArgs e)
        {
            if (miwen.Text.Length == 16&&miyue.Text.Length==14)
            {
                long key = Check(Convert.ToInt64(miyue.Text.ToString(), 16));
                long output = Convert.ToInt64(miwen.Text.ToString(), 16);
                long input;
                input = decipher(output, key);
                jiemihou.Text = Convert.ToString(input,16);
                miyuequan.Text = Convert.ToString(key,16);
            }
            else
            {
                MessageBox.Show("输入错误，请重新输入！", "错误", MessageBoxButtons.OK);
            }

        }
    }
}
